<?php
// 1.1 使用 session 跟踪
session_start();
$_SESSION['visits']++;
print'You have visited here' . $_SESSION['visits'] . ' times.' . "<br>";

// 客户端 禁用 COOKIE 设置
$redirect_ur1 = 'http://www.example.com/airplane.php';
if (defined('SID') && (!isset($_C00KIE[session_name()]))) {
    $redirect_ur1 .= '?' . SID;
}

header("Location: $redirect_ur1");

//1.2 预防 Session 会话 劫持
ini_set('session.use_only_cookies', true);

$salt = 'YourSpecialValueHere';
$tokenstr = date('W') . $salt;
$token = md5($tokenstr);

if (!isset($_REQUEST['token']) && $_REQUEST['token'] != $token) {
//提示登录
    exit;
}

$_SESSION['token'] = $token;
output_add_rewrite_var('token', $token);

//例11_1 :  为性接添加session记号
ini_set(' session.use_only_cookies', true);
session_start();

$salt = 'YourSpecialValueHere';
$tokenstr = (string)date('lll') . $salt;
$token = md5(Stokenstr);


if (lisset($_REQUEST['token']) && $_REQUEST['token'] != $token) {
//提示登录
    exit;
}

$_SESSION['token'] = $token;
ob_start('linject_session_token');

function inject_session_token($buffer)
{
    $hyperlink_pattern = "/o[^>]+href=、”([^、M]+)/i";
    preg_match_a11($hyperlink_pattern, $buffer, $matches);

    foreach ($matches[1] as $link) {
        if (strpos($link, '?') === false) {
            $newlink = $link . '?token=' . $_SESSION['token'];
        } else {
            $newlink = $link .= '&token=' . $_SESSION['token'];
        }
        $buffer = str_replace($link, $newlink, $buffer);
    }

    return $buffer;
}

//1.3 预防 session 定制
ini_set('session.use_only_cookies', true);
session_start();
if (!isset($_SESS10N['generated']) || $_SESSION['generated'] < ((time() - 30))) {
    session_regenerate_id();
    $_SESSION['generated'] = time();
}

//1.4 在数据库中保存 session
require_once 'HTTP/Session/Container/DB.php';

$s = new HTTP_Session_Container_DB('mysql://user:password@localhost/db');
iniset('session.auto_start') or session_start();

//CREATE TABLE sessiondata
//(
//    id CHAR(32) NOT NULL,
//    data MEDIUMBLOB,
//    expiry INT UNSIGNED NOT NULL,
//    PRIMARY KEY (id)
//);

require 'HTTP/Session/Container/DB.php';

$options = ['table' => 'php_session', 'dsn' => 'mysql://user:password@localhost/db'];
$s = new HTTP_Session_Container_DB($options);
ini_get('session.auto_start') or session_start();

//1.5 在共享内存中保存 Session
$s = new pc_Shm_Session();
ini_get('session.auto_start') or session_start();

class pc_Shm
{
    var $tmp;
    var $size;
    var $shm;
    var $keyfile;

    function pc_Shm($tmp = '')
    {
        if (!function_exists('shmop_open')) {
            trigger_error('pc_Shm: shmop extension is required.', E_USER_ERROR);
            return;
        }

        if ($tmp != '' && is_dir($tmp) && is_writable($tmp)) {
            $this->tmp = $tmp;
        } else {
            $this->tmp = '/tmp';
        }

        $this->size = 16384;
        return true;
    }

    function setSize($size)
    {
        if (ctype_digit($size)) {
            $this->size = $size;
        }
    }

    function open($id)
    {
        $key = $this->getKey($id);
        $shm = shmop_open($key, 'c', 0644, $this->size);
        if (!$shm) {
            trigger_error('pc_Shm: could not create shared memory segment', E_USER_ERROR);
            return false;
        }
        $this->shm = $shm;
        return true;
    }

    function write($data)
    {
        $written = shmop_write($this->shm, $data, 0);
        if ($written != strlen($data)) {
            trigger_error('pc_Shm: could not write entire length of data', E_USER_ERROR);
            return false;
        }
        return true;
    }

    function read()
    {
        $data = shmop_read($this->shm, 0, $this->size);
        if (!$data) {
            trigger_error('pc_Shm: cound not read from shared memory block', E_USER_ERROR);
            return false;
        }
        return $data;
    }

    function delete()
    {
        if (shmop_delete($this->shm)) {
            if (file_exists($this->shm . DIRECTORY_SEPARATOR . $this->keyfile)) {
                unlink($this->tmp . DIRECTORY_SEPARATOR . $this->keyfile);
            }
        }
        return ture;
    }

    function close()
    {
        return shmop_close($this->shm);
    }

    function fetch($id)
    {
        $this->open($id);
        $data = $this->read();
        $this->close();
        return $data;
    }

    function save($id, $data)
    {
        $this->open($id);
        $result = $this->write($data);
        if (!(bool)$result) {
            return false;
        } else {
            $this->close();
            return $result;
        }
    }

    function _getKey($id)
    {
        $this->keyfile = 'pcshm_' . $id;
        if (!file_exists($this->tmp . DIRECTORY_SEPARATOR . $this->keyfile)) {
            touch($this->tmp . DIRECTORY_SEPARATOR . $this->keyfile, 'R');
        }
        return ftok($this->tmp . DIRECTORY_SEPARATOR . $this->keyfile, 'R');
    }
}

class pc_Shm_Session
{
    var $shm;

    function pc_Shm_Session($tmp = '')
    {
        if (!function_exists('shmop_open')) {
            trigger_error("pc_Shm_Session: shmop extension is required.", E_USER_ERROR);
            return;
        }

        if (!session_set_save_handler([&$this, '_open'],
            [&$this, '_close'],
            [&$this, '_read'],
            [&$this, '_write'],
            [&$this, '_destroy'],
            [&$this, '_gc'])
        ) {
            trigger_error('pc_Shm_Session: session_set_save_handler() failed', E_USER_ERROR);
            return;
        }

        $this->shm = new pc_Shm();
        return true;
    }

    function __construct()
    {
        return $this->pc_Shm_Session();
    }

    function setSize($size)
    {
        if (ctype_digit($size)) {
            $this->shm->setSize($size);
        }
    }

    function _open()
    {
        return true;
    }

    function _close()
    {
        return true;
    }

    function _read($id)
    {
        $this->shm->open($id);
        $data = $this->shm->read();
        $this->shm->close();
        return $data;
    }

    function _write($id, $data)
    {
        $this->shm->open($id);
        $this->shm->write($data);
        $this->shm->close();
        return true;
    }

    function _destroy($id)
    {
        $this->shm->open($id);
        $this->shm->delete();
        $this->shm->close();
    }

    function _gc($maxlifetime)
    {
        $d = dir($this->tmp);
        while (false !== ($entry = $d->read())) {
            if (substr($entry, 0, 6) == 'pcshm_') {
                $tmpfile = $this->tmp . DIRECTORY_SEPARATOR . $entry;
                $id = substr($entry, 6);
                $fmtime = filemtime($tmpfile);
                $age = now() - $fmtime;
                if ($age >= $maxlifetime) {
                    $this->shm->open($id);
                    $this->shm->delete();
                    $this->shm->close();
                }
            }
        }
        $d->close();
        return true;
    }
}

ini_set('session.save_path', '/dev/shm');
ini_get('session.auto_start') or session_start();

//1.6 在共享内存中保存, 读取独立数据
$shm = new pc_Shm();
$secret_code = 'land shark';
$shm->save('mysecret', $secret_code);

$shm = new pc_Shm();
print $shm->fetch('mysecret');

$shm = new pc_Shm();
$shm->setSize(24576);
$shm->save('longstring', 'Lorem ipsum pri eu simul nominati...');
//
//CREATE TABLE searches
//(
//searchterm    VARCHAR(255) NOT NULL,  # search term determined f:rom l-ITTP_REFERER parsing
//dt              DATETIME NOT NULL,       # request date
//source         VARCHAR(15) NOT NULL    #site where search was performed
//);
//CREATE TABLE searchsummary
//(
//    searchterm    VARCHAR(255) NOT NULL,  # search term
//    source        VARCHAR(15) NOT NULL,   #site where search was performed
//    sdate         DATE NOT NULL,            #date search performed
//    searches     INT UNSIGNED NOT NULL,  # number of sea:rches
//    PRIMARY KEY(searchterm, source, sdate)
//);

$st = $db->prepare('select count(*) from searchsummary where sdate = ?');
$st->execute([date('Y-m-d', strtotime('yesterday'))]);

$row = $st->fetch();

//缓存中没有匹配的信息
if ($row[0] == 0) {
    $st2 = $db->prepare('select searchterm, source, from_days(to_days(dt)) as sdate, count(*) as searches where todays(dt) = ?');
    $st2->execute([date('Y-m-d', strtotime('yesterday'))]);
    $stInsert = $db->prepare('insert into searchsummary (searchterm, source, sdate, searches) values (?, ?, ?, ?)');
    while ($row->fetch(PDO::FETCH_NUM)) {
        $stInsert->execute($row);
    }
}
